#include "../libc/list.h"
#include "pci.h"
#include "usb.h"

extern list_t *pci_list;

static void do_usb_init(pci_dev_t *d);
static int ehci_reset(ehci_regs_t *r);
static void ehci_control_xfer(ehci_regs_t *r);

static uint8_t __attribute__((aligned(4096))) buf[4096];

static inline void mmio_write32(uintptr_t addr, uint32_t val)
{
    *(volatile uint32_t *)addr = val;
}
static inline uint32_t mmio_read32(uintptr_t addr)
{
    return *(volatile uint32_t *)addr;
}

int usb_init() {
    if(pci_list->size == 0) return 0;
    node_t *n = &(pci_list->n);
    int i;
    for(i = 0; i < pci_list->size;i++) {
        n = n->next;
        pci_dev_t *d = n->data;
        if(d->class_code == 0x0c && d->sub_class == 0x03) {
            do_usb_init(d);
        }
    }
    return 0;
}

void usb_read(int sector, uint8_t *addr);

static void do_usb_init(pci_dev_t *d) {
    if(d->proif == 0x20) {
        ehci_regs_t *r = (ehci_regs_t *)(d->bar[0] + 0x10);
        int res = ehci_reset(r);
        if(res) {
            ehci_control_xfer(r);
            // 设备描述符
            uint8_t *desc = buf + 192;
            if (desc[0] == 0x12 && desc[1] == 0x01) {
                // 成功获取
                
            }
        }
    }
}

static int ehci_reset(ehci_regs_t *r)
{
    /* 停止调度 */
    mmio_write32((uintptr_t)&r->usbcmd, 0);

    /* 等待 RUN 位清 0 */
    while (mmio_read32((uintptr_t)&r->usbcmd) & (1 << 0))
        ;

    /* 复位控制器 */
    mmio_write32((uintptr_t)&r->usbcmd, 1 << 1);
    while (mmio_read32((uintptr_t)&r->usbcmd) & (1 << 1))
        ;

    /* 路由端口到 EHCI */
    mmio_write32((uintptr_t)&r->configflag, 1);

    /* 打开端口电源并等待连接 */
    mmio_write32((uintptr_t)&r->portsc[0],
        mmio_read32((uintptr_t)&r->portsc[0]) | (1 << 12));
    return mmio_read32((uintptr_t)&r->portsc[0]) & (1 << 0);
}

/* 构建一个控制传输：SETUP -> DATA -> STATUS */
static void ehci_control_xfer(ehci_regs_t *r)
{
    /* 描述符放在 4K 对齐缓冲区 */
    qh_t *qh  = (qh_t *)buf;
    qtd_t *qtd = (qtd_t *)(buf + 64);

    /* 设备描述符请求 8 字节 */
    static const uint8_t setup[] = {
        0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00
    };

    /* ---- 初始化 qTD ---- */
    /* SETUP qtd */
    qtd[0].next = (uintptr_t)&qtd[1] | 1;      /* 指向下一个 qTD，T=1 表示最后一个 */
    qtd[0].alt  = 1;                           /* 不跳转 */
    qtd[0].token = (8 << 16) | (2 << 8) | 0x80; /* 8 字节, PID=SETUP, Status=Active */

    /* DATA qtd */
    qtd[1].next = (uintptr_t)&qtd[2] | 1;
    qtd[1].alt  = 1;
    qtd[1].token = (8 << 16) | (1 << 8) | 0x80; /* 8 字节, PID=IN   */

    /* STATUS qtd */
    qtd[2].next = 1;        /* 结束 */
    qtd[2].alt  = 1;
    qtd[2].token = (0 << 16) | (0 << 8) | 0x80; /* 0 字节, PID=OUT  */

    /* 复制 SETUP 数据到缓冲区 */
    uint8_t *setup_buf = (uint8_t *)&qtd[3];
    int i;
    for (i = 0; i < 8; i++) setup_buf[i] = setup[i];
    qtd[0].buf[0] = (uintptr_t)setup_buf;

    /* DATA 缓冲区 */
    uint8_t *data_buf = (uint8_t *)&qtd[4];
    qtd[1].buf[0] = (uintptr_t)data_buf;

    /* ---- 初始化 QH ---- */
    qh->horizontal = 1;                 /* 终止 */
    qh->static_ep  = (1 << 27) |        /* C=1 */
                     (0x00 << 16) |     /* 端点 0 */
                     (0x40 << 0);       /* 高速 */
    qh->overlay[0] = (uintptr_t)qtd;

    /* 把 QH 物理地址写进 ASYNCLIST */
    mmio_write32((uintptr_t)&r->asynclistaddr, (uintptr_t)qh);
    mmio_write32((uintptr_t)&r->usbcmd, (1 << 5) | 1); /* 打开异步调度 + RUN */

    /* 轮询完成标志 */
    while (qtd[2].token & 0x80)
        ;

    /* 关闭调度 */
    mmio_write32((uintptr_t)&r->usbcmd, 0);
}